/**
 * 家具相关模型
 */
import A3ObjectTypes from "../../A3ObjectTypes.js";
import A3ObjectGroup from "../../A3ObjectGroup.js";
import A3Object from "../../A3Object.js";
import { updateObjectTexture } from "../../common/Common.js";

/**
 * 自动门
 */
class A3RevolvedDoor extends A3ObjectGroup {

  type=A3ObjectTypes.RevolvedDoor;
  name=A3ObjectTypes.RevolvedDoor;

  mass = 0.0;

  // 门铰链参数
  isReversal = false;
  jointMaxImpulse = 9999;
  jointMaxVelocity = 10;
  hingeLimit = [ 0, Math.PI / 2 ];
  _softness = 0.1;
  _biasFactor = 0.3
  _relaxationFactor = 1.0;

  enableBaseShape = true;

  isOpenable = true;


  defaultTexture = {
    Front: {
      url:"../../../textures/door.jpg",
      size: [ -1, -1 ],
      offset:[0, 0],
      center:[0.5, 0.5],
      rotation:0
    },
    Back: {
      url:"../../../textures/door.jpg",
      size: [ -1, -1 ],
      offset:[0, 0],
      center:[0.5, 0.5],
      rotation:Math.PI
    }
  }

  constructor( width, height, depth, isReversal=false ) {

    super( width, height, depth, true );

    this.meshType = "box"; // "cylinder";
    this.isReversal = isReversal;

    if( isReversal ) {
      this.hingeLimit[0] = -Math.PI / 2;
      this.hingeLimit[1] = 0
    }

    this.init();
    
    this.initActions();

    // this.enalbeAxes();
    this.enableShadow();

    this.initChildren( );

  }

  init(){

    const width = this.width;
    const height = this.height;
    // const depth = this.depth;
    super.init( width - 2, height, width );
    this.setColor( .7, .7, .7 );
    updateObjectTexture( this, this.defaultTexture );
    this.visual.visible = true;

  }

  initChildren() {

    const width = this.width;
    const height = this.height;
    const depth = this.depth;

    // 门
    const door = new A3Object( width, height, depth - width, "box" );

    door.setColor( .7, .7, .7 );
    door.setPosition( 0, 0, -(depth - width) / 2 );
    updateObjectTexture( door, this.defaultTexture );

    // 取消重力影响
    door.disableGravity = true;

    this.addChild( door );
    // 添加约束
    const newConstraint = {
      type:"hinge",

      indexA:0,
      indexB:1,
      originInA: [ 0, 0, 0 ],
      rotationInA: [ Math.PI/2, 0, 0 ],
      originInB: [ 0, 0, (depth - width) / 2 ],
      rotationInB: [ Math.PI/2, 0, 0 ],
      useReferenceFrameA: true,

      handle:undefined,

    }

    this.constraints.push( newConstraint );

    this.door = door;
    
  }

  initActions(){
    super.initActions();

    this.addAction( "open", "KeyO", this.open.bind(this) );
    this.addAction( "close", "KeyC", this.close.bind(this) );
    this.addAction( "stop", "KeyT", this.stop.bind(this) );

  }

  setLimit( low, upper ) {
    this.hingeLimit[0] = low;
    this.hingeLimit[1] = upper;
  }
  
  stop() {

    const hinge = this.constraints[0];
    const handle = hinge.handle;

    if( handle ) {

      handle.enableAngularMotor( true, 0, this.jointMaxImpulse );

    }

  }

  open() {

    const hinge = this.constraints[0];
    const handle = hinge.handle;

    if( handle ) {
      handle.setLimit( 
        this.hingeLimit[0], 
        this.hingeLimit[1], 
        this._softness,
        this._biasFactor,
        this._relaxationFactor
      );
      // handle.setBreakingImpulseThreshold( 1000 );
      handle.enableAngularMotor( true, this.isReversal? -this.jointMaxVelocity : this.jointMaxVelocity, this.jointMaxImpulse );
    }

  }

  close() {

    const hinge = this.constraints[0];
    const handle = hinge.handle;

    if( handle ) {

      handle.setLimit( 
        this.hingeLimit[0], 
        this.hingeLimit[1], 
        this._softness,
        this._biasFactor,
        this._relaxationFactor
      );

      handle.enableAngularMotor( true, this.isReversal? this.jointMaxVelocity : -this.jointMaxVelocity, this.jointMaxImpulse );
    }

  }

/******* ******* ******* ******* ******* ******* *******/
/******* 导入导出 *******/
/******* ******* ******* ******* ******* ******* *******/
  toJson() {

    const data = super.toJson();

    data["jointMaxImpulse"] = this.jointMaxImpulse;
    data["jointMaxVelocity"] = this.jointMaxVelocity;
    data["hingeLimit"] = this.hingeLimit;
    data["_softness"] = this._softness;
    data["_biasFactor"] = this._biasFactor;
    data["_relaxationFactor"] = this._relaxationFactor;

    return data;

  }

  static fromJson( data, obj, passChild=false ) {

    if ( obj === null || obj === undefined ) {
      obj = new A3RevolvedDoor( data.width, data.height, data.depth );
    }

    // 取消自动加载子演员
    super.fromJson( data, obj, true );

    obj["jointMaxImpulse"] = data.jointMaxImpulse;
    obj["jointMaxVelocity"] = data.jointMaxVelocity;
    obj["hingeLimit"] = data.hingeLimit;
    obj["_softness"] = data._softness;
    obj["_biasFactor"] = data._biasFactor;
    obj["_relaxationFactor"] = data._relaxationFactor;

    return obj;

  }

}

export {
  A3RevolvedDoor,
}